<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>定时任务管理</title>
    <link rel="stylesheet" href="./layui/css/layui.css">
    <link rel="stylesheet" href="/static/iconfont/iconfont.css">
    <style>
        body {
            background-color: #eeeeee;
            padding: 20px;
        }

        .mt6 {
            margin-top: 6px;
        }

        .text-right {
            text-align: right;
        }

        .layui-input-group {
            display: flex;
        }

        .layui-input-group .layui-input-side {
            border: 1px solid #E6E6E6;
            border-right-width: 0;
            white-space: nowrap;
            line-height: 36px;
            color: #888;
            padding: 0 12px;
        }

        .layui-input-group .layui-input {
            border-right-width: 0;
            border-radius: 0;
        }

        .layui-input-group > *:first-child {
            border-radius: 2px 0 0 2px;
        }

        .layui-input-group > *:last-child {
            border-radius: 0 2px 2px 0;
            border-right-width: 1px;
        }

        .layui-card-header {
            display: flex;
            height: auto;
            min-height: 42px;
            line-height: 1;
            align-items: center;
        }

        .card-header-title {
            width: 100%;
        }

        .card-header-toolbar {
            white-space: nowrap;
            padding: 10px 0;
            font-size: 0;
        }

        .logs-code .layui-layer-content {
            padding: 0 !important;
            background-color: #000000;
        }

        .logs-code .layui-code {
            margin: 0;
        }

        .edit-form-model .layui-layer-content {
            margin-top: 40px;
            margin-right: 40px;
        }
    </style>
</head>
<body>

<div class="layui-collapse" style="margin-bottom: 20px">
    <div class="layui-colla-item">
        <h2 class="layui-colla-title layui-bg-blue">添加定时任务</h2>
        <div class="layui-colla-content" style="background-color: #ffffff">
            <div class="layui-row">
                <div class="layui-col-xs6">
                    <form class="layui-form" action="" id="addForm">
                        <div class="layui-form-item layui-row layui-col-space16">
                            <label class="layui-col-sm2 mt6 text-right">任务类型</label>
                            <div class="layui-col-sm10">
                                <select name="sType" lay-filter="sType">
                                    <option value="toShell">Shell脚本</option>
                                    <option value="toUrl">访问URL</option>
                                </select>
                            </div>
                        </div>

                        <div class="layui-form-item layui-row layui-col-space16">
                            <label class="layui-col-sm2 mt6 text-right">任务名称</label>
                            <div class="layui-col-sm10">
                                <input type="text" name="name" autocomplete="off" placeholder=""
                                       class="layui-input">
                            </div>
                        </div>

                        <div class="layui-form-item layui-row layui-col-space16">
                            <label class="layui-col-sm2 mt6 text-right">执行周期</label>
                            <div class="layui-col-sm10">
                                <div class="layui-row layui-col-space16">
                                    <div class="layui-col-xs3">
                                        <select name="type" lay-filter="type">
                                            <option value="day">每天</option>
                                            <option value="day-n">N天</option>
                                            <option value="hour">每小时</option>
                                            <option value="hour-n">N小时</option>
                                            <option value="minute-n">N分钟</option>
                                            <option value="week" selected>每星期</option>
                                            <option value="month">每月</option>
                                        </select>
                                    </div>
                                    <div class="layui-col-xs3" data-react-type="week">
                                        <select name="week">
                                            <option value="0">周日</option>
                                            <option value="1">周一</option>
                                            <option value="2">周二</option>
                                            <option value="3">周三</option>
                                            <option value="4">周四</option>
                                            <option value="5">周五</option>
                                            <option value="6">周六</option>
                                        </select>
                                    </div>
                                    <div class="layui-col-xs3 layui-input-group" data-react-type="where1"
                                         style="display: none;">
                                        <input type="number" name="where1" autocomplete="off" class="layui-input"
                                               value="3" maxlength="2" max="31" min="1">
                                        <span class="layui-input-side">日</span>
                                    </div>
                                    <div class="layui-col-xs3 layui-input-group" data-react-type="hour">
                                        <input type="number" name="hour" autocomplete="off" placeholder=""
                                               class="layui-input" value="1">
                                        <span class="layui-input-side">小时</span>
                                    </div>
                                    <div class="layui-col-xs3 layui-input-group" data-react-type="minute">
                                        <input type="number" name="minute" autocomplete="off" placeholder=""
                                               class="layui-input" value="30">
                                        <span class="layui-input-side">分钟</span>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <div class="layui-form-item layui-row layui-col-space16" data-cron-type="toShell">
                            <label class="layui-col-sm2 mt6 text-right">执行脚本</label>
                            <div class="layui-col-sm10">
                                <textarea placeholder="请输入脚本内容" rows="20" class="layui-textarea" name="sBody"></textarea>
                            </div>
                        </div>

                        <div class="layui-form-item layui-row layui-col-space16" data-cron-type="toUrl"
                             style="display: none;">
                            <label class="layui-col-sm2 mt6 text-right">URL地址</label>
                            <div class="layui-col-sm10">
                                <input type="text" name="urladdress" autocomplete="off" placeholder="http://"
                                       class="layui-input">
                            </div>
                        </div>


                        <div class="layui-form-item layui-row layui-col-space16">
                            <label class="layui-col-sm2 mt6 text-right"></label>
                            <div class="layui-col-sm10">
                                <button type="submit" class="layui-btn" lay-submit="" lay-filter="add">添加任务</button>
                            </div>
                        </div>

                    </form>
                </div>
                <div class="layui-col-xs6"></div>
            </div>
        </div>
    </div>
</div>

<div class="layui-card">
    <div class="layui-card-header">
        <div class="card-header-title">任务列表</div>
        <div class="card-header-toolbar">
            <button type="button" style="display: none" class="multiple-btn layui-btn layui-btn-sm" id="startAll">执行选中
            </button>
            <button type="button" style="display: none" class="multiple-btn layui-btn layui-btn-danger layui-btn-sm"
                    id="delAll">删除选中
            </button>
        </div>
    </div>
    <div class="layui-card-body">
        <table class="layui-hide" id="crontabTable" lay-filter="table"></table>
    </div>
</div>

<script src="./layui/layui.js" charset="utf-8"></script>
<script>
    layui.use(['form', 'table', 'code','element'], function () {
        let form = layui.form,
            table = layui.table,
            layer = layui.layer,
            $ = layui.jquery;

        let msg = {
            "CRONTAB_TODAY": "每天",
            "CRONTAB_TODAY_CYCLE": "每天, {0}点{1}分执行",
            "CRONTAB_N_TODAY": "每{0}天",
            "CRONTAB_N_TODAY_CYCLE": "每隔{0}天, {1}点{2}分执行",
            "CRONTAB_HOUR": "每小时",
            "CRONTAB_HOUR_CYCLE": "每小时, 第{0}分钟 执行",
            "CRONTAB_N_HOUR": "每{0}小时",
            "CRONTAB_N_HOUR_CYCLE": "每{0}小时, 第{1}分钟 执行",
            "CRONTAB_N_MINUTE": "每{0}分钟",
            "CRONTAB_N_MINUTE_CYCLE": "每隔{0}分钟执行",
            "CRONTAB_WEEK": "每周",
            "CRONTAB_WEEK_CYCLE": "每周{0}, {1}点{2}分执行",
            "CRONTAB_MONTH": "每月",
            "CRONTAB_MONTH_CYCLE": "每月, {0}日 {1}点{2}分执行",
        };

        String.prototype.format = function (args) {
            let result = this;
            if (arguments.length < 1) {
                return result;
            }

            let data = arguments;		//如果模板参数是数组
            if (arguments.length === 1 && typeof (args) == "object") {
                //如果模板参数是对象
                data = args;
            }

            for (let key in data) {
                if (data.hasOwnProperty(key)) {
                    let value = data[key];
                    if (undefined !== value) {
                        result = result.replace("{" + key + "}", value);
                    }
                }
            }
            return result;
        };

        let Renders = {
            typeRender: function (row) {
                let week = ['日', '一', '二', '三', '四', '五', '六'];
                switch (row.type) {
                    case 'day':
                        return {
                            type: msg.CRONTAB_TODAY,
                            cycle: msg.CRONTAB_TODAY_CYCLE.format(row.where_hour, row.where_minute)
                        };
                    case 'day-n':
                        return {
                            type: msg.CRONTAB_N_TODAY.format(row.where1),
                            cycle: msg.CRONTAB_N_TODAY_CYCLE.format(row.where1, row.where_hour, row.where_minute)
                        };
                    case 'hour':
                        return {
                            type: msg.CRONTAB_HOUR,
                            cycle: msg.CRONTAB_HOUR_CYCLE.format(row.where_minute)
                        };
                    case 'hour-n':
                        return {
                            type: msg.CRONTAB_N_HOUR.format(row.where1),
                            cycle: msg.CRONTAB_N_HOUR_CYCLE.format(row.where1, row.where_minute)
                        };
                    case 'minute-n':
                        return {
                            type: msg.CRONTAB_N_MINUTE.format(row.where1),
                            cycle: msg.CRONTAB_N_MINUTE_CYCLE.format(row.where1)
                        };
                    case 'week':
                        if (!row.where1) row.where1 = '0';
                        return {
                            type: msg.CRONTAB_WEEK,
                            cycle: msg.CRONTAB_WEEK_CYCLE.format(week[row.where1], row.where_hour, row.where_minute)
                        };
                    case 'month':
                        return {
                            type: msg.CRONTAB_MONTH,
                            cycle: msg.CRONTAB_MONTH_CYCLE.format(row.where1, row.where_hour, row.where_minute)
                        };
                }
            },
            type: function (row) {
                return Renders.typeRender(row).type
            },
            cycle: function (row) {
                return Renders.typeRender(row).cycle
            },
            status: function (row) {
                let btn = '<span style="color: green;cursor:pointer" data-disable-task="' + row.id + '" title="停用该计划任务">正常 <i class="iconfont icon-play" style="font-size: 13px"></i></span>';
                if (row.status.toString() !== '1') {
                    btn = '<span style="color: red;cursor:pointer" data-enable-task="' + row.id + '" title="启用该计划任务">停用 <i class="iconfont icon-pause" style="font-size: 13px"></i></span>';
                }
                return btn;
            },
            operate: function (row) {
                let btn = '';
                btn += '<a style="color: green" data-start-task="' + row.id + '" href="javascript:;">执行</a> | ';
                btn += '<a style="color: green" data-edit-task="' + row.id + '" href="javascript:;">编辑</a> | ';
                btn += '<a style="color: green" data-get-logs="' + row.id + '" href="javascript:;">日志</a> | ';
                btn += '<a style="color: green" data-del-task="' + row.id + '" href="javascript:;">删除</a>';
                return btn;
            }
        };

        let Table = table.render({
            id: 'crontabTable',
            elem: '#crontabTable',
            url: '/index.php?a=get_crontab_list',
            parseData: function (res) {
                return {
                    "code": res.code,
                    "msg": res.msg,
                    "count": res.data.count,
                    "data": res.data.list
                };
            },
            cols: [[
                {type: 'checkbox'},
                {field: 'name', title: '任务名称'},
                {field: 'type', width: '12%', title: '周期', templet: Renders.type},
                {field: 'cycle', width: '20%', title: '执行时机', templet: Renders.cycle},
                {field: 'addtime', width: 170, title: '添加时间'},
                {field: 'status', width: 80, title: '状态', templet: Renders.status},
                {field: 'operate', width: 180, title: '操作', templet: Renders.operate}
            ]],
            skin: 'line',
            even: true
        });

        var cycleOption = {
            'day': ['hour', 'minute'],
            'day-n': ['where1', 'hour', 'minute'],
            'hour': ['minute'],
            'hour-n': ['hour', 'minute'],
            'minute-n': ['minute'],
            'week': ['week', 'hour', 'minute'],
            'month': ['where1', 'hour', 'minute'],
        };

        // 改变执行周期
        form.on('select(type)', function (data) {
            let f = $(data.elem.form);
            $('[data-react-type]', f).hide();
            $.each(cycleOption[data.value], function (i, el) {
                $('[data-react-type=' + el + ']', f).show();
                if (data.value === 'month') {
                    $('input[name=where1]', f).attr('min', 1);
                    $('[data-react-type=where1] .layui-input-side', f).text('日');
                }
                if (data.value === 'day-n') {
                    $('input[name=where1]', f).attr('min', 0);
                    $('[data-react-type=where1] .layui-input-side', f).text('天');
                }
            })
        });

        // 改变任务类型
        form.on('select(sType)', function (data) {
            let f = $(data.elem.form);
            $('[data-cron-type]', f).hide();
            $('[data-cron-type=' + data.value + ']', f).show()
        });

        //自定义验证规则
        // form.verify({
        //     title: function (value) {
        //         if (value.length < 5) {
        //             return '标题至少得5个字符啊';
        //         }
        //     }
        //     , pass: [
        //         /^[\S]{6,12}$/
        //         , '密码必须6到12位，且不能出现空格'
        //     ]
        //     , content: function (value) {
        //         layedit.sync(editIndex);
        //     }
        // });

        //监听指定开关
        // form.on('switch(switchTest)', function (data) {
        //     layer.msg('开关checked：' + (this.checked ? 'true' : 'false'), {
        //         offset: '6px'
        //     });
        //     layer.tips('温馨提示：请注意开关状态的文字可以随意定义，而不仅仅是ON|OFF', data.othis)
        // });

        let submitCycleFormat = function (data) {
            switch (data.type) {
                case 'day':
                    data.where1 = '';
                    data.week = '';
                    break;
                case 'day-n':
                    data.week = '';
                    break;
                case 'hour':
                    data.where1 = '';
                    data.hour = '';
                    data.week = '';
                    break;
                case 'hour-n':
                    data.where1 = data.hour;
                    data.hour = '';
                    data.week = '';
                    break;
                case 'minute-n':
                    data.where1 = data.minute;
                    data.hour = '';
                    data.minute = '';
                    data.week = '';
                    break;
                case 'week':
                    data.where1 = data.week;
                    break;
                case 'month':
                    data.week = '';
                    break;
            }
            return data;
        };

        //监听提交
        form.on('submit(add)', function (data) {
            data.field = submitCycleFormat(data.field);
            let index = layer.load();
            $.ajax({
                url: 'index.php?a=add_crontab',
                type: 'POST',
                dataType: 'json',
                data: data.field,
                success: function (res) {
                    layer.close(index);
                    if (res.code.toString() === '0') {
                        layer.msg('操作成功', {icon: 1});
                        Table.reload();
                    } else {
                        layer.msg(res.msg || '操作失败', {icon: 2});
                    }
                },
                error: function () {
                    layer.close(index);
                    layer.msg('服务器异常，请稍候重试', {icon: 2});
                }
            });
            return false;
        });

        form.on('submit(edit)', function (data) {
            data.field = submitCycleFormat(data.field);
            let index = layer.load();
            $.ajax({
                url: 'index.php?a=edit_crontab&id=' + data.field.id,
                type: 'POST',
                dataType: 'json',
                data: data.field,
                success: function (res) {
                    layer.close(index);
                    if (res.code.toString() === '0') {
                        layer.closeAll();
                        layer.msg('操作成功', {icon: 1});
                        Table.reload();
                    } else {
                        layer.msg(res.msg || '操作失败', {icon: 2});
                    }
                },
                error: function () {
                    layer.close(index);
                    layer.msg('服务器异常，请稍候重试', {icon: 2});
                }
            });
            return false
        });

        table.on('checkbox(table)', function () {
            let checkStatus = table.checkStatus('crontabTable');
            if (checkStatus.data.length > 0) {
                $('.multiple-btn').show();
            } else {
                $('.multiple-btn').hide();
            }
        });

        // 执行任务
        let startTask = function (ids) {
            let msg = ids.length > 1 ? '现在开始执行选中的{0}个任务吗？'.format(ids.length) : '现在开始执行这个任务吗？';
            layer.confirm(msg, {icon: 3, title: '提示'}, function (index) {
                $.get('/index.php?a=start_task&ids=' + ids.join(','), function (res) {
                    layer.closeAll();
                    if (res.code.toString() === '0') {
                        layer.msg('执行成功', {icon: 1});
                    } else {
                        layer.msg(res.msg || '操作失败', {icon: 2});
                    }
                });
            });
        };
        // 删除任务
        let delTask = function (ids) {
            let msg = ids.length > 1 ? '确定要删除选中的{0}个任务吗？'.format(ids.length) : '确定要删除这个任务吗？';
            layer.confirm(msg, {icon: 3, title: '提示'}, function (index) {
                layer.load();
                $.get('/index.php?a=del_crontab&ids=' + ids.join(','), function (res) {
                    layer.closeAll();
                    if (res.code.toString() === '0') {
                        layer.msg('删除成功', {icon: 1});
                        Table.reload();
                    } else {
                        layer.msg(res.msg || '操作失败', {icon: 2});
                    }
                });
            });
        };
        // 启用任务
        let enableTask = function (ids) {
            let msg = ids.length > 1 ? '确定要启用选中的{0}个任务吗？'.format(ids.length) : '确定要启用这个任务吗？';
            layer.confirm(msg, {icon: 3, title: '提示'}, function (index) {
                layer.load();
                $.get('/index.php?a=set_status&id=' + ids.join(','), function (res) {
                    layer.closeAll();
                    if (res.code.toString() === '0') {
                        layer.msg('操作成功', {icon: 1});
                        Table.reload();
                    } else {
                        layer.msg(res.msg || '操作失败', {icon: 2});
                    }
                })
            });
        };
        // 停用任务
        let disableTask = function (ids) {
            let msg = ids.length > 1 ? '确定要停用选中的{0}个任务吗？'.format(ids.length) : '确定要停用这个任务吗？';
            layer.confirm(msg, {icon: 3, title: '提示'}, function (index) {
                layer.load();
                $.get('/index.php?a=set_status&id=' + ids.join(','), function (res) {
                    layer.closeAll();
                    if (res.code.toString() === '0') {
                        layer.msg('操作成功', {icon: 1});
                        Table.reload();
                    } else {
                        layer.msg(res.msg || '操作失败', {icon: 2});
                    }
                })
            });
        };
        $('body').on('click', '[data-edit-task]', function () {
            // 编辑任务
            let id = $(this).data('edit-task');
            let index = layer.load();
            $.get('/index.php?a=edit_crontab&id=' + id, function (res) {
                layer.close(index);
                layer.open({
                    area: ['800px'],
                    skin: 'edit-form-model',
                    btn: '',
                    type: 1,
                    content: '<form class="layui-form" id="editForm" lay-filter="editForm">' + $('#addForm').html() + '</form>',
                    success: function () {
                        let f = $('#editForm');
                        $('button[type=submit]', f).attr('lay-filter', 'edit').text('保存修改');
                        f.append('<input name="id" type="hidden" />');
                        f.append('<input name="echo" type="hidden" />');
                        res.data.hour = res.data.where_hour;
                        res.data.minute = res.data.where_minute;
                        switch (res.data.type) {
                            case 'minute-n':
                                res.data.minute = res.data.where1;
                                break;
                            case 'week':
                                res.data.week = res.data.where1;
                                break;
                            case 'hour-n':
                                res.data.hour = res.data.where1;
                                break;
                        }
                        console.log(res.data)
                        form.val('editForm', res.data);
                        $('.layui-form-select dl dd.layui-this', f).trigger('click');
                        $('select[name=sType]', f).attr('disabled', true);
                        form.render();
                    }
                });
            })
        }).on('click', '[data-get-logs]', function () {
            // 获取任务日志
            let id = $(this).data('get-logs');
            let index = layer.load();
            $.ajax({
                url: '/index.php?a=get_logs&id=' + id,
                success: function (res) {
                    layer.close(index);
                    if (res.code.toString() === '0') {
                        layer.open({
                            skin: 'logs-code',
                            area: ['60%', '600px'],
                            content: '<pre class="layui-code" lay-encode="true" lay-skin="notepad">' + $('<div/>').html(res.data.content).text() + '</pre>',
                            btn: ['清空', '关闭'],
                            btn1: function (index, layero) {
                                layer.load();
                                $.get('/index.php?a=clear_logs&id=' + id, function (res) {
                                    layer.closeAll();
                                    if (res.code.toString() === '0') {
                                        layer.msg('清除成功', {icon: 1});
                                    }
                                });
                                return false
                            },
                            success: function () {
                                layui.code({
                                    about: false,
                                    title: res.data.name,
                                    encode: true
                                });
                            }
                        });
                    } else {
                        layer.msg(res.msg || '操作失败', {icon: 2});
                    }
                },
                error: function () {
                    layer.close(index);
                    layer.msg('服务器异常，请稍候重试', {icon: 2});
                }
            });
        }).on('click', '[data-start-task]', function () {
            // 执行任务
            let id = $(this).data('start-task');
            startTask([id]);
        }).on('click', '[data-del-task]', function () {
            // 删除任务
            let id = $(this).data('del-task');
            delTask([id]);
        }).on('click', '[data-enable-task]', function () {
            // 启用任务
            let id = $(this).data('enable-task');
            enableTask([id]);
        }).on('click', '[data-disable-task]', function () {
            // 停用任务
            let id = $(this).data('disable-task');
            disableTask([id]);
        }).on('click', '#startAll', function () {
            // 批量执行任务
            let checkStatus = table.checkStatus('crontabTable');
            let ids = checkStatus.data.map(function (v) {
                return v.id
            });
            if (ids.length > 0) {
                startTask(ids);
            }
        }).on('click', '#delAll', function () {
            // 批量删除任务
            let checkStatus = table.checkStatus('crontabTable');
            let ids = checkStatus.data.map(function (v) {
                return v.id
            });
            if (ids.length > 0) {
                delTask(ids);
            }
        })

        //表单赋值
        // layui.$('#LAY-component-form-setval').on('click', function () {
        //     form.val('example', {
        //         "username": "贤心" // "name": "value"
        //         , "password": "123456"
        //         , "interest": 1
        //         , "like[write]": true //复选框选中状态
        //         , "close": true //开关状态
        //         , "sex": "女"
        //         , "desc": "我爱 layui"
        //     });
        // });

        //表单取值
        // layui.$('#LAY-component-form-getval').on('click', function () {
        //     var data = form.val('example');
        //     alert(JSON.stringify(data));
        // });

    });
</script>
</body>
</html>